package com.polaris.live.ui.live.fragment

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.Activity
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.Utils
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import com.gyf.immersionbar.ImmersionBar
import com.lxj.xpopup.core.BasePopupView
import com.polaris.live.R.drawable
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.PagConst
import com.polaris.live.common.ext.autoDp
import com.polaris.live.common.ext.convertArabicDigitsToNormal
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.network.EncryptHelper
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.LogExt
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.common.util.ifDestroy
import com.polaris.live.constant.EventConst
import com.polaris.live.constant.LiveConst
import com.polaris.live.constant.TrackEventConst
import com.polaris.live.constant.UserConst
import com.polaris.live.constant.ZegoGameEvent
import com.polaris.live.databinding.FragmentGameCallLiveVideoBinding
import com.polaris.live.dialog.CallHangUpDialog
import com.polaris.live.dialog.GlobalDialogManager
import com.polaris.live.dialog_fragment.GiftDialogFragment
import com.polaris.live.im.manager.ImCallManager
import com.polaris.live.im.sfs.CALL_GAME_ANSWER
import com.polaris.live.im.sfs.CALL_GAME_STATUS
import com.polaris.live.im.sfs.CALL_LOAD_GAME
import com.polaris.live.im.sfs.CALL_OTHER_CAMERA
import com.polaris.live.im.sfs.CALL_REFUSE_INTERPRETATION
import com.polaris.live.im.sfs.COMMAND_CALL_ANSWER
import com.polaris.live.im.sfs.COMMAND_CALL_END
import com.polaris.live.im.sfs.COMMAND_CALL_NO_ANSWER
import com.polaris.live.im.sfs.COMMAND_CALL_REFUSE
import com.polaris.live.im.sfs.LIVE_MASKING_MESSAGE
import com.polaris.live.im.sfs.LIVE_OCCLUSION_MESSAGE
import com.polaris.live.im.sfs.LIVE_RECHARGE_PAY
import com.polaris.live.im.sfs.LIVE_RELOAD_GAME
import com.polaris.live.im.sfs.LIVE_SEND_GIFT
import com.polaris.live.im.sfs.LIVE_TRANSLATION_MESSAGE
import com.polaris.live.im.sfs.LIVE_WARN_MESSAGE
import com.polaris.live.im.sfs.REQUEST_GIFT_POPUP_MESSAGE
import com.polaris.live.im.sfs.bean.live.CallSignalingMessage
import com.polaris.live.im.sfs.bean.live.ext.UserBasicVo
import com.polaris.live.im.sfs.bean.live.payload.CallGameStatusPayloadDto
import com.polaris.live.im.sfs.bean.live.payload.CallLaunchRechargePayloadBean
import com.polaris.live.im.sfs.bean.live.payload.CallObstructPayloadBean
import com.polaris.live.im.sfs.bean.live.payload.CallStreamSwitchPayloadDto
import com.polaris.live.im.sfs.bean.live.payload.InviteGiftPayloadBean
import com.polaris.live.im.sfs.bean.live.payload.InviteGiftPopupPayloadDto
import com.polaris.live.im.sfs.bean.live.payload.SimultaneousStartPayloadBean
import com.polaris.live.popup.CallGameBalancePopup
import com.polaris.live.popup.GlobalPopupManager
import com.polaris.live.popup.PublicTipsPopup
import com.polaris.live.popup.RequestGiftPopup
import com.polaris.live.popup.SetTranslationPopup
import com.polaris.live.popup.WeeklyStarPopup
import com.polaris.live.resp.back_resp.CallStartResp
import com.polaris.live.resp.back_resp.CallVo
import com.polaris.live.resp.back_resp.InfoOtherResp
import com.polaris.live.resp.back_resp.PartyGameResp
import com.polaris.live.resp.back_resp.RecognizeModel
import com.polaris.live.resp.back_resp.toUserBasicVo
import com.polaris.live.resp.bean.ZegoGameEventBean
import com.polaris.live.resp.event.BackgroundEvent
import com.polaris.live.resp.go_resp.SendGiftBean
import com.polaris.live.translation.R
import com.polaris.live.ui.live.fragment.base.GestureFragment
import com.polaris.live.ui.live.proxy.LiveMoreProxy
import com.polaris.live.ui.live.proxy.LivePublicProxy
import com.polaris.live.ui.live.proxy.caller.CallGameVideoListenerProxy
import com.polaris.live.ui.live.proxy.gift.CallGiftAnimationProxy
import com.polaris.live.ui.live.widget.listener.OnBackPressedListener
import com.polaris.live.ui.live.widget.listener.OnCallEventListener
import com.polaris.live.ui.live.widget.listener.OnChangeCameraListener
import com.polaris.live.ui.live.widget.listener.OnGameCallListener
import com.polaris.live.ui.live.widget.listener.OnLiveCallCallback
import com.polaris.live.ui.live.widget.listener.OnTranslationChangeListener
import com.polaris.live.ui.message.fragment.MessageSessionFragment
import com.polaris.live.ui.message.fragment.dialog.MessageSingleDialogFragment
import com.polaris.live.ui.party.fragment.game.GamePlayFragment
import com.polaris.live.utils.LiveUtils
import com.polaris.live.utils.TrackHelper
import com.polaris.live.utils.XPopupUtils
import com.polaris.live.utils.fragment.FragmentUtils
import com.polaris.live.utils.fragment.showNewDialogFragment
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.postEvent
import com.polaris.live.utils.zego.LiveEngineManage
import com.polaris.live.utils.zego.core.ZegoGameEngineHandler
import com.polaris.live.utils.zego.listener.PreGameListener
import com.polaris.live.viewmodel.live.CallVideoViewModel
import im.zego.minigameengine.ZegoGameEngineError
import im.zego.minigameengine.ZegoGameLoadState
import im.zego.minigameengine.ZegoGamePlayerState
import im.zego.minigameengine.ZegoGameState
import im.zego.zegoexpress.callback.IZegoEventHandler
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.nio.charset.StandardCharsets

/**
 * GameCallVideoFragment        游戏打电话模式拨打方和接听方的fragment
 *
 * @author Created by 天晴 on 2024/4/19/012 17:10
 */
class GameCallVideoFragment :
    GestureFragment<CallVideoViewModel, FragmentGameCallLiveVideoBinding>(),
    OnBackPressedListener,
    OnCallEventListener,
    OnChangeCameraListener {

    //通话的基本信息
    private val mCallInfo by lazy {
        arguments?.getParcelable<CallVo>(LiveConst.Params.CALL_INFO)
            ?: throw IllegalArgumentException("callModel is null")
    }

    private val mRoomId by lazy {
        "call${mCallInfo.id}"
    }

    private var mIsSwitchExchange = false //是否是nogGame模式
    private var mCallBean: CallStartResp? = null //接收方的信息
    private var mCallMessage: CallSignalingMessage? = null //拨打方的信息
    private var mOtherUserBasic: UserBasicVo? = null //对方的的基本信息

    private val mLiveMoreProxy by lazy {
        LiveMoreProxy(
            requireContext(), this, mViewModel,
            pageType,
            this,
            null
        )
    }
    private val mLivePublicProxy by lazy {
        LivePublicProxy(requireContext(), mViewModel)
    }

    private val mCallVideoListenerProxy by lazy {
        CallGameVideoListenerProxy(
            requireContext(),
            mBinding
        )
    }
    private var isInitTranslation = false

    private var isFree = false

    //礼物动画代理
    private var mGiftAnimProxy: CallGiftAnimationProxy? = null
    private val mGiftDialog by lazy {
        GiftDialogFragment(
            AppConst.GiftComming.CALL,
            AppConst.BackpackGiftComming.CALL,
            null,
            true
        ) { giftSendBean ->
            val sendGiftBean = SendGiftBean(
                getOtherUserId(),
                giftSendBean.gift.id,
                giftSendBean.num,
                AppConst.GiftComming.CALL,
                mCallInfo.id,
                giftSendBean.backpackId,
                giftSendBean.gift.payload
            )
            mViewModel.sendGift(
                requireContext(),
                sendGiftBean,
                LiveConst.SendGift.giftPopup,
                giftSendBean.gift.pic,
                false
            )
        }.also {
            ifDestroy {
                if (it.fragmentManager != null) {
                    //因为当LifecycleOwner回调ON_DESTROY的时候fragment的状态已经保存了，此时再调用FragmentManager相关的东西就会报IllegalStateException
                    if (isAdded && !isStateSaved) {
                        it.dismiss()
                    } else {
                        it.dismissAllowingStateLoss()
                    }
                }
            }
        }
    }

    private var mPlayFirstFrame: Boolean = false

    private var mCloseCamera: Boolean = false //关闭自己摄像头
    private var mCloseOtherCamera: Boolean = false //对方关闭自己摄像头

    private var mCallGameBalancePopup: BasePopupView? = null

    private var mOnGameCallListener: OnGameCallListener? = null
    private var mOnLiveCallCallback: OnLiveCallCallback? = null

    //同声传译设置后回调
    private var mOnTranslateChange: OnTranslationChangeListener? = null
    private val mEventHandler = object : IZegoEventHandler() {
        override fun onPlayerSyncRecvSEI(streamID: String?, data: ByteArray) {
            super.onPlayerSyncRecvSEI(streamID, data)
            mViewModel.viewModelScope.launch {
                try {
                    val str = String(data, StandardCharsets.UTF_8).substring(LiveConst.ZEGONUM)
                    if (!TextUtils.isEmpty(str)) {
                        mBinding.vTransition.onTranslationText(
                            getOtherUser(),
                            GsonUtils.fromJson(str, RecognizeModel::class.java)
                        )
                    }
                } catch (_: Exception) {
                }
            }
        }
    }

    /**
     * game-----------------------
     */
    private var mGameLoad = false // 游戏是否加载
    private var mStartLoadGameTime = 0L
    private var mReloadGame = false // 重新加载游戏
    private val mGameMiniId: String = "Black8" // 游戲id
    private var mMuteSoundVoice = false
    private var mLocalGameStatus = GAME_UNLOAD  //本地游戏状态
    private var mPartyGameInfo: PartyGameResp? = null //单个游戏信息
    private var mGameStatus = 0  //游戏状态 0 等待中 1已准备好 2进行中  3已结束

    private var lastIndex = 3

    private fun initImmersionBar() {
        ImmersionBar.with(this)
            .transparentBar()
            .titleBarMarginTop(mBinding.llTitle)
            .init()

        NavigationBarUtils.setNavigationHeight(mBinding.llBottom)
        NavigationBarUtils.setNavigationHeight(mBinding.vTransition)
    }

    //初始化同声传译
    private fun initTranslation(iv: String, translationLanguage: String?) {
        if (isInitTranslation) return
        val key = mCallInfo.simultaneousEncrypt?.let { EncryptHelper.decryptParams(it, iv) }
        val speechLanguage = UserManager.getUser().profile?.spokenLanguage
        if (key != null && translationLanguage != null && speechLanguage != null) {
            mOnTranslateChange?.onInitTranslation(key, translationLanguage, speechLanguage)
            isInitTranslation = true
        }
    }

    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)
        initImmersionBar()

        EventBus.getDefault().register(this)
        LiveEngineManage.eventHandlerHelper.addEventHandler(mEventHandler)
        LiveEngineManage.gameEventHandlerHelper.observe(this, mZegoGameEngineHandler)

        mOnGameCallListener?.setGameCallView(mBinding.tvPlay, mBinding.tvMian)
        //理论上数据不可能为空，为空不往下走
        mCallBean = arguments?.getParcelable(LiveConst.Params.CALL_BEAN)
        mCallMessage = arguments?.getParcelable(LiveConst.Params.CALL_MESSAGE)
        mOtherUserBasic = arguments?.getParcelable(LiveConst.Params.CALL_USER_BASIC)

        mGiftAnimProxy = CallGiftAnimationProxy(
            requireContext(),
            mBinding.llGift,
            viewLifecycleOwner,
            mViewModel
        )

        initUi()
        initListener()
        initObserve()
    }

    override fun initData() {
        super.initData()
        updateGameStatus(mGameStatus)
        mCallInfo.gameType?.let {
            mViewModel.getOnePartyGame(it)
        }

        /**
         * 接听方获取周星数据
         */
        if (isAnswer() && mCallMessage?.earnings == 0L) {
            mViewModel.getWeeklyStarRank()
        }
    }

    private fun initUi() {
        mBinding.apply {
            val otherSex: Int?
            //接收方取message
            if (isAnswer()) {
                val callMessage = mCallMessage
                otherSex = if (callMessage != null) {
                    vHeader.initData(pageType, mCallInfo, callMessage)
                    callMessage.sex
                } else {
                    val userBasic = mOtherUserBasic
                    if (userBasic != null) {
                        vHeader.initData(pageType, mCallInfo, userBasic)
                    }
                    userBasic?.sex
                }
            } else {//播打方取bean
                val userBasic = mCallBean?.answer ?: mOtherUserBasic
                if (userBasic != null) {
                    vHeader.initData(pageType, mCallInfo, userBasic)
                }
                otherSex = userBasic?.sex
            }
            vTransition.initData(
                otherSex,
                mCallBean?.answer?.avatar,
                mCallBean?.answer?.avatarFrame,
                isPayer()
            )
            if (mCallBean?.call?.simulInterpret == true) {
                vTransition.setDragTranslationViewVisibility(View.VISIBLE)
                startTransitionPag()
            } else {
                vTransition.setDragTranslationViewVisibility(View.GONE)
                stopTransitionPag()
            }
            isFree = mCallMessage?.earnings == 0L

            startTransitionPag()
            //如果语言相同隐藏同声传译
            if (mCallBean?.call?.sameLanguage == true) {
                transitionBtn.visibility = View.GONE
                mOnTranslateChange?.onTranslationSwitch(false)
            } else {
                mOnTranslateChange?.onTranslationSwitch(true)
                transitionBtn.visibility = View.VISIBLE
            }
            UserManager.getUser().let {
                avatarImg.setImageUrl(it.avatar, it.userId)
                nameTv.text = it.nickname
                nameTv.setNicknameColor(
                    it.decoration?.nicknameColor,
                    com.polaris.live.R.color.white
                )
            }
            getOtherUser()?.let {
                avatarImg2.setImageUrl(it.avatar, it.userId)
                nameTv2.text = it.nickname
                nameTv2.setNicknameColor(
                    it.nicknameColor,
                    com.polaris.live.R.color.white
                )
            }
            vEdit.initData(mCallInfo)
        }
    }

    private fun startTransitionPag() {
        mBinding.apply {
            transitionBtn.visibility = View.VISIBLE
            mBinding.transitionBtn.apply {
                visibility = View.VISIBLE
                path = PagConst.TRANSLATION_PAG
                setRepeatCount(-1)
                play()
            }
        }
    }

    private fun stopTransitionPag() {
        mBinding.apply {
            transitionBtn.pause()
            transitionBtn.visibility = View.GONE
        }
    }

    private fun initListener() {
        mBinding.apply {
            /**
             * 展示详情弹窗
             */
            weekStar.setShowDetail {
                WeeklyStarPopup.showPop(requireContext(), this@GameCallVideoFragment, mViewModel, lastIndex) {
                    lastIndex = it
                }
            }
            /**
             * 周星是否显示数据
             */
            weekStar.setShowWeekStarCallBack {
                if (it) {
                    mViewModel.pollingWeeklyStarRank()
                } else {
                    mViewModel.cancelPollingWeeklyStarRank()
                }
            }
            ivCamera.setOnSingleClickListener {
                mCloseCamera = !mCloseCamera
                mOnGameCallListener?.onGameOpenCloseCamera(mCloseCamera, mBinding.tvPlay)

                if (mCloseCamera) {
                    mBinding.cvMain.visibility = View.GONE
                    mBinding.cvMainImg.visibility = View.VISIBLE
                    Glide.with(requireContext())
                        .load(ImageUtils.imgPath(UserManager.getUser().avatar))
                        .transform(BlurTransformation(15, 15))
                        .into(mBinding.playImg)
                    Glide.with(requireContext())
                        .load(ImageUtils.imgPath(UserManager.getUser().avatar))
                        .apply(RequestOptions.circleCropTransform())
                        .into(mBinding.playImgCir)
                } else {
                    mBinding.cvMain.visibility = View.VISIBLE
                    mBinding.cvMainImg.visibility = View.GONE

                }
                mViewModel.streamSwitch(mCallInfo.id, !mCloseCamera)

                ivCamera.setImageResource(if (mCloseCamera) drawable.game_call_camera_close else drawable.game_call_camera_open)
            }
            /**
             * 切换模式
             */
            switchTv.setOnSingleClickListener {
                openFull()
                vTransition.foldAndUnfold(true)
            }
            /**
             * 切换模式
             */
            cvRight.setOnSingleClickListener {
                openFull()
                vTransition.foldAndUnfold(true)
            }
            /**
             * 切换模式
             */
            switchBtn.setOnSingleClickListener {
                closeFull()
            }
            /**
             * 切换模式
             */
            backGame.setOnSingleClickListener {
                closeFull()
            }
            //点击关注
            vHeader.setOnFollowerClickListener {
                mViewModel.addFollower(getOtherUserId())
            }
            //点击主播头像
            vHeader.setOnAvatarClientListener {
                //等待接听的状态无需展示
                if (isStarted()) return@setOnAvatarClientListener
                showUserProfilePopup(getOtherUserId())
            }
            //显示头像
            vMessage.mBinding.baseMessage.setOnUserProfileClickListener {
                showUserProfilePopup(it)
            }
            avatarImg.setOnSingleClickListener {
                showUserProfilePopup(UserManager.getUserId())
            }
            avatarImg2.setOnSingleClickListener {
                showUserProfilePopup(getOtherUserId())
            }

            //显示输入框
            ivSend.setOnSingleClickListener {
                vEdit.showKeyboard()
            }
            //发送公屏消息
            vEdit.setOnSendPublicMessageListener {
                mViewModel.sendPublicMessage(it)
            }
            //点击更多
            callMore.setOnSingleClickListener {
                val otherUserId = getOtherUser()?.userId
                val otherNickname = getOtherUser()?.nickname
                if (otherUserId != null && otherNickname != null) {
                    val callId = mCallInfo.id
                    mLiveMoreProxy.showVideoMore(otherUserId, otherNickname, callId, {
                        mBinding.vEdit.setKeyboardListerState(it)
                    })
                }
            }
            //关闭视频
            closeVideo.setOnSingleClickListener {
                showStopPopup()
            }
            //点击隐藏edit
            ViewUtils.registerTouchDown(mianCl) {
                vEdit.hideKeyboard()
            }
            //显示礼物
            ivGift.setOnSingleClickListener {
                getOtherUser()?.also {
                    showGiftDialog(it.avatar, it.avatarFrame)
                }
            }
            //赠送关注礼物
            vMessage.mBinding.baseMessage.setOnSendFollowerListener {
                mViewModel.sendGift(
                    requireContext(),
                    it,
                    LiveConst.SendGift.followerGift,
                    null,
                    false
                )
            }
            //赠送礼物
            vMessage.mBinding.baseMessage.setOnSendGiftListener {
                mViewModel.sendGift(
                    requireContext(),
                    it,
                    LiveConst.SendGift.publicGift,
                    null,
                    false
                )
            }

            btnVoice.setOnSingleClickListener {
                mMuteSoundVoice = !mMuteSoundVoice
                muteSound()
            }
            btnWen.setOnSingleClickListener {
                mPartyGameInfo?.let { partyGameInfo ->
                    GlobalDialogManager.showGameRuleDialog(
                        requireContext(),
                        partyGameInfo.slogan
                    )
                } ?: mCallInfo.gameType?.let { gameType ->
                    mViewModel.getOnePartyGame(gameType)
                }
            }
            //点击同声传译区域
            vTransition.setClickCallback {
                transitionBtn.performClick()
            }
            //同声传译
            transitionBtn.setOnSingleClickListener {
                val isShow = isAnswer()
                XPopupUtils.showPopup(
                    SetTranslationPopup(
                        requireActivity(),
                        isShow,
                        mCallBean?.call?.simulInterpret,
                        mViewModel, {
                            mOnTranslateChange?.onSetSpeechLanguage(it)
                        }, {
                            mCallBean?.call?.simulInterpret = it
                            if (it) {
                                isFree = false
                                vTransition.setDragTranslationViewVisibility(View.VISIBLE)
                                startTransitionPag()
                            } else {
                                vTransition.setDragTranslationViewVisibility(View.GONE)
                                stopTransitionPag()
                            }

                            mCallBean?.call?.id?.let { it1 ->
                                mOnTranslateChange?.onTranslationSwitch(it)
                                mViewModel.openSwimultaneous(it1, it)
                            }
                        }),
                    lifecycle = lifecycle
                )
            }
            /**
             * 准备
             */
            joinBtn.setOnSingleClickListener {
                mViewModel.callGameReady(mCallInfo.id, LiveConst.GameBusinessType.CALL, true)
                joinBtn.visibility = View.GONE
                exitGame.visibility = View.VISIBLE
            }
            /**
             * 取消准备
             */
            exitGame.setOnSingleClickListener {
                mViewModel.callGameReady(mCallInfo.id, LiveConst.GameBusinessType.CALL, false)
                joinBtn.visibility = View.VISIBLE
                exitGame.visibility = View.GONE
            }
        }

    }

    private val mOnAppStatusChangedListener = object : Utils.OnAppStatusChangedListener {
        override fun onForeground(activity: Activity?) {
            mViewModel.stopKillActivityTimeout()
            mViewModel.isForeground = true
        }

        override fun onBackground(activity: Activity?) {
            mViewModel.isForeground = false
            mViewModel.killActivityTimeout(maxBackgroundTime)
        }
    }

    private fun initObserve() {
        AppUtils.registerAppStatusChangedListener(mOnAppStatusChangedListener)
        /**
         * 周星数据更新
         */
        mViewModel.weeklyStarRankData.observe(this) { state ->
            parseState(state, {
                if (it.show) {
                    mViewModel.cancelPollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.VISIBLE
                    it.base?.let { da ->
                        mBinding.weekStar.setData(da)
                    }
                } else {
                    mViewModel.pollingWeeklyStarRank()
                    mBinding.weekStar.visibility = View.GONE
                }
            }, {
                //报错开启定时请求
                mViewModel.pollingWeeklyStarRank()
            })
        }

        //发送礼物后如果position不为空那么代表就是送的邀请关注礼物
        mViewModel.sendFollowerLiveData.observe(this) {

        }
        mViewModel.callConnectLiveData.observe(this) { state ->
            parseState(state, {
                startCallSuccessful(it.getTime)
                if (isPayer()) {
                    mViewModel.getCallPromotion()
                }
                if (it.ivParameter != null) {
                    initTranslation(it.ivParameter, it.translationLanguage)
                }
            }, {
                //失败直接通知结束
                stopCallFailure()
            })
        }

        //关注主播
        mViewModel.followerLiveData.observe(this) { resultState ->
            parseState(resultState, {
                ToastGravity.showGravity(com.polaris.live.translation.R.string.follower_succeed)
                mBinding.vMessage.mBinding.baseMessage.clearFollower()
                mBinding.vHeader.updateFollowStatus(true)
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
        //心跳检测
        mViewModel.callHeartbeatLiveData.observe(this) { resultState ->
            parseState(resultState, {
                mCallVideoListenerProxy.onCheckCallBackChange(it)
            })
        }
        mViewModel.callHeartbeatFailureLiveData.observe(this) {
            if (it) {
                //失败需要断开
                stopCallFailure()

                //如果是出现异常则调用通话结束
                mViewModel.callEnd(mCallInfo.id, LiveConst.CloseType.ERROR, UserManager.getUserId())
            }
        }
        //通话计时
        mViewModel.callCountdownLiveData.observe(this) {
            mBinding.answerTimeText.text =
                LiveUtils.formatTime(it).convertArabicDigitsToNormal()
        }
        //关闭通话
        mViewModel.callEndLiveData.observe(this) { state ->
            parseState(state, {
                stopCallSuccessful(it)
            }, {
                stopCallSuccessful(null)
            })
        }
        //等待接听超时
        mViewModel.answerTimeoutLiveData.observe(this) {
            if (isAnswer()) {
                //如果是应答方需要主动结束
                mViewModel.callEnd(
                    mCallInfo.id,
                    LiveConst.CloseType.TIMEOUT,
                    UserManager.getUserId()
                )
            } else {
                stopCallSuccessful(null)
            }
        }
        //通话公屏消息
        ImCallManager.observePublicMessage(this, { mCallInfo.id }, { message ->
            if (message.type in ImCallManager.publicTypes && message.businessId == mCallInfo.id) {
                mBinding.vMessage.addMessage(message)
            }

            //其他消息处理
            when (message.type) {
                //拉起充值页面
                LIVE_RECHARGE_PAY -> {
                    val payload = message.payload as CallLaunchRechargePayloadBean
                    GlobalPopupManager.showRechargePopup(
                        requireContext(),
                        mViewModel,
                        message.content,
                        payload.duration,
                        isNeedBottom = true
                    )
                }
                //礼物动画
                LIVE_SEND_GIFT -> {
                    val payload = message.payload as InviteGiftPayloadBean
                    if (payload.gift.animation != null) {
                        mBinding.widgetGift.setGift(payload)
                    } else {
                        mGiftAnimProxy?.addGift(message)
                    }
                }
                //遮挡消息
                LIVE_OCCLUSION_MESSAGE -> {
                    val payload = message.payload as CallObstructPayloadBean
                    if (payload.obstruct) {
                        if (!mBinding.llObstruct.isVisible) {
                            playAnim(listOf(inAlpha(mBinding.llObstruct)))
                        }
                    } else {
                        if (mBinding.llObstruct.isVisible) {
                            playAnim(listOf(outAlpha(mBinding.llObstruct)))
                        }
                    }
                }
                //遮罩消息
                LIVE_MASKING_MESSAGE -> {
                    mBinding.maskView.maskState(message)
                }
                //警告消息
                LIVE_WARN_MESSAGE -> {
                    mLivePublicProxy.onPublicMessage(message)
                }
                //同声传译开关
                LIVE_TRANSLATION_MESSAGE -> {
                    val payload = message.payload as SimultaneousStartPayloadBean
                    if (payload.open) {
                        isFree = false
                        if (!isInitTranslation && !payload.ivParameter.isNullOrEmpty() && !payload.translationLanguage.isNullOrEmpty()) {
                            initTranslation(payload.ivParameter, payload.translationLanguage)
                        }
                        mCallBean?.call?.simulInterpret = true
                        mBinding.vTransition.setDragTranslationViewVisibility(View.VISIBLE)
                        startTransitionPag()
                    } else {
                        mCallBean?.call?.simulInterpret = false
                        mBinding.vTransition.setDragTranslationViewVisibility(View.GONE)
                        stopTransitionPag()
                    }

                    mOnTranslateChange?.onTranslationSwitch(payload.open)
                }

                LIVE_RELOAD_GAME -> { //重新加载游戏
                    reloadGame()
                }

                CALL_GAME_STATUS -> { //通话游戏状态
                    val payload = message.payload as CallGameStatusPayloadDto
                    handlerGameUserInfo(payload)
                }

                CALL_GAME_ANSWER -> { //通话游戏开始
                    mViewModel.gameStart(mCallInfo.id, LiveConst.GameBusinessType.CALL)
                }

                CALL_OTHER_CAMERA -> { //对方控制了摄像头
                    val payload = message.payload as CallStreamSwitchPayloadDto
                    mCloseOtherCamera = !payload.open

                    mOnGameCallListener?.onGameOtherOpenCloseCamera(
                        mCloseOtherCamera,
                        if (mIsSwitchExchange) mBinding.fullscreenTv else mBinding.tvMian
                    )
                    if (mIsSwitchExchange) {
                        if (mCloseOtherCamera) {
                            mBinding.fullscreenTv.visibility = View.GONE
                            mBinding.fullscreenFl.visibility = View.VISIBLE
                            Glide.with(requireContext())
                                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                                .transform(BlurTransformation(15, 15))
                                .into(mBinding.fullscreenImg)
                            Glide.with(requireContext())
                                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                                .apply(RequestOptions.circleCropTransform())
                                .into(mBinding.fullscreenImgaCir)
                        } else {
                            mBinding.fullscreenTv.visibility = View.VISIBLE
                            mBinding.fullscreenFl.visibility = View.GONE
                        }
                    } else {
                        if (mCloseOtherCamera) {
                            mBinding.cvMinor.visibility = View.GONE
                            mBinding.cvMinorImg.visibility = View.VISIBLE
                            Glide.with(requireContext())
                                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                                .transform(BlurTransformation(15, 15))
                                .into(mBinding.mianImg)
                            Glide.with(requireContext())
                                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                                .apply(RequestOptions.circleCropTransform())
                                .into(mBinding.mianImgCir)
                        } else {
                            mBinding.cvMinor.visibility = View.VISIBLE
                            mBinding.cvMinorImg.visibility = View.GONE
                        }
                    }
                }

                CALL_LOAD_GAME -> { //游戏加载消息
                    loadGame()
                }

                CALL_REFUSE_INTERPRETATION -> { //拒绝同声传译
                    PublicTipsPopup.show(
                        requireContext(), this,
                        StringUtils.getString(R.string.prompt),
                        message.content,
                        StringUtils.getString(R.string.continue_connecting),
                        StringUtils.getString(R.string.end_connection)
                    ) {
                        val type = if (isStarted()) {
                            LiveConst.CloseType.CANCEL
                        } else {
                            LiveConst.CloseType.END
                        }
                        mViewModel.callEnd(mCallInfo.id, type, UserManager.getUserId(), true)
                    }
                }

                REQUEST_GIFT_POPUP_MESSAGE -> { //索要礼物弹出消息
                    val payload = message.payload as InviteGiftPopupPayloadDto
                    RequestGiftPopup.show(
                        requireContext(), this,
                        payload, {
                            mViewModel.inviteGift(mCallInfo.id)
                        }
                    )
                }
            }
        })
        ImCallManager.observe(this, { mCallInfo.id }) {
            //已打通
            withMessage<CallSignalingMessage>(COMMAND_CALL_END) {
                stopCallSuccessful(it.getCallVo() ?: mCallInfo)
            }
            //对方已接通
            withMessage<CallSignalingMessage>(COMMAND_CALL_ANSWER) {
                if (isStarted()) {
                    onAnswerSuccess(it)
                }
            }
            //未打通
            withMessage<CallSignalingMessage>(COMMAND_CALL_NO_ANSWER) {
                if (isStarted()) {
                    stopCallSuccessful(null)

                    ToastGravity.showGravity(com.polaris.live.translation.R.string.call_no_answer)
                }
            }
            withMessage<CallSignalingMessage>(COMMAND_CALL_REFUSE) {
                if (isStarted()) {
                    stopCallSuccessful(null)
                    lifecycleScope.launch(CoroutineScopeManager.mainDispatcher) {
                        ToastGravity.showGravity(com.polaris.live.translation.R.string.call_request_denied)
                    }
                }
            }
        }
        //开始游戏
        mViewModel.gameStartData.observe(this) { resultState ->
            parseState(resultState, {
                startGame()
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
        //准备
        mViewModel.callGameReadyData.observe(this) { resultState ->
            parseState(resultState, {

            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
        //获取单个派对游戏
        mViewModel.getOnePartyGameData.observe(this) { resultState ->
            parseState(resultState, {
                mPartyGameInfo = it
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
    }

    private fun showGiftDialog(avatar: String, avatarFrame: String?) {
        val fragmentManager = FragmentUtils.getFragmentManager(requireContext())
            ?: return

        mGiftDialog.apply {
            setUserId(getOtherUserId(), getOtherUser()?.nickname)
            show(fragmentManager, GiftDialogFragment.FRAGMENT_TAG)
        }
    }

    /**
     * 打开全屏
     */
    private fun openFull() {
        mIsSwitchExchange = true
        val leftTv = mBinding.tvPlay
        val rightTv = mBinding.fullscreenTv
        narrow()
        mOnGameCallListener?.setGameCallView(leftTv, rightTv)
        mBinding.switchBtn.visibility = View.VISIBLE
        mBinding.backGame.visibility = View.GONE
        mBinding.cvRight.visibility = View.GONE
        mBinding.vsImg.visibility = View.GONE
        mBinding.startCl.visibility = View.INVISIBLE
        mBinding.gameFl.visibility = View.INVISIBLE
        if (mCloseOtherCamera) {
            mBinding.fullscreenTv.visibility = View.GONE
            mBinding.fullscreenFl.visibility = View.VISIBLE
            Glide.with(requireContext())
                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                .transform(BlurTransformation(15, 15))
                .into(mBinding.fullscreenImg)
            Glide.with(requireContext())
                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                .apply(RequestOptions.circleCropTransform())
                .into(mBinding.fullscreenImgaCir)
        } else {
            mBinding.fullscreenTv.visibility = View.VISIBLE
            mBinding.fullscreenFl.visibility = View.GONE
        }
    }

    private fun closeFull() {
        mIsSwitchExchange = false
        val leftTv = mBinding.tvPlay
        val rightTv = mBinding.tvMian
        mOnGameCallListener?.setGameCallView(leftTv, rightTv)
        mBinding.fullscreenTv.visibility = View.GONE
        mBinding.fullscreenFl.visibility = View.GONE
        mBinding.switchBtn.visibility = View.GONE
        mBinding.backGame.visibility = View.GONE
        mBinding.cvRight.visibility = View.VISIBLE
        mBinding.startCl.visibility = View.VISIBLE

        if (mLocalGameStatus == GAME_START_PLAY) {
            mBinding.gameFl.visibility = View.VISIBLE
            mBinding.vsImg.visibility = View.VISIBLE
        } else {
            mBinding.vsImg.visibility = View.GONE
            mBinding.gameFl.visibility = View.INVISIBLE
            enlarge()
        }

        if (mCloseOtherCamera) {
            mBinding.cvMinor.visibility = View.GONE
            mBinding.cvMinorImg.visibility = View.VISIBLE
            Glide.with(requireContext())
                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                .transform(BlurTransformation(15, 15))
                .into(mBinding.mianImg)
            Glide.with(requireContext())
                .load(ImageUtils.imgPath(getOtherUser()?.avatar))
                .apply(RequestOptions.circleCropTransform())
                .into(mBinding.mianImgCir)
        } else {
            mBinding.cvMinor.visibility = View.VISIBLE
            mBinding.cvMinorImg.visibility = View.GONE
        }
    }

    /**
     * 辅助处理用户信息
     */
    private fun handlerGameUserInfo(data: CallGameStatusPayloadDto) {
        if (data.userId == UserManager.getUserId()) {
            mBinding.avShape.setBackgroundResource(if (data.userReady) drawable.shape_circle_00ff2a else drawable.shape_circle_ffffff)
            mBinding.avShape2.setBackgroundResource(if (data.answerReady) drawable.shape_circle_00ff2a else drawable.shape_circle_ffffff)
            mBinding.correct.visibility = if (data.userReady) View.VISIBLE else View.GONE
            mBinding.correct2.visibility = if (data.answerReady) View.VISIBLE else View.GONE
        } else {
            mBinding.avShape.setBackgroundResource(if (data.answerReady) drawable.shape_circle_00ff2a else drawable.shape_circle_ffffff)
            mBinding.avShape2.setBackgroundResource(if (data.userReady) drawable.shape_circle_00ff2a else drawable.shape_circle_ffffff)
            mBinding.correct.visibility = if (data.answerReady) View.VISIBLE else View.GONE
            mBinding.correct2.visibility = if (data.userReady) View.VISIBLE else View.GONE
        }
        updateGameStatus(data.gameStatus)
        //处理结果 没在全屏视频时才弹窗
        if (data.gameStatus == 3 && !mIsSwitchExchange) {
            val callGameBalancePopup = mCallGameBalancePopup
            if (callGameBalancePopup == null || !callGameBalancePopup.isShow) {
                getOtherUser()?.let {
                    mCallGameBalancePopup = CallGameBalancePopup.show(requireContext(), it, data)
                }
            }
        }
    }

    private fun connected() {
        //拿到对方的帧可以开始通话了
        mViewModel.callConnect(mCallInfo.id)

        mCallInfo.status = LiveConst.CallState.ANSWER
    }

    private fun startCallSuccessful(getTime: Long) {
        mCallInfo.status = LiveConst.CallState.CONNECTED
        mCallInfo.getTime = getTime

        handleConnectView()

        //通话终于建立了
        mCallBean.apply {
            mViewModel.launchCallHeartbeat(mCallInfo.id, getTime)
            mViewModel.launchCallCountdown(getTime)

            LiveUtils.resolveScreenshotStrategy(LiveConst.Page.CALL, mCallInfo.screenshotStrategy)
                ?.also {
                    mViewModel.launchScreenshot(pageType, mCallInfo.id, getTime, it)
                }
        }
    }

    //已接通
    private fun handleConnectView() {
        mBinding.callMore.visibility = View.VISIBLE
        mBinding.llBottom.visibility = View.VISIBLE
        mBinding.tvCalling.hideWaiting()
    }

    //最终错误的结束通话
    private fun stopCallFailure() {
        stopCallSuccessful(null)
    }

    //最终成功的结束通话
    private fun stopCallSuccessful(callInfo: CallVo?) {
        if (isEnded()) {
            return
        }
        mOnLiveCallCallback?.onCallStop(callInfo, mCallBean, mCallMessage, mViewModel.isForeground)

        mViewModel.resetLiveJob()

        mCallInfo.status = LiveConst.CallState.OVER
    }

    private fun showUserProfilePopup(userId: Long) {
        GlobalPopupManager.showUserProfilePopup(
            requireContext(), this, mViewModel,
            userId, UserConst.From.LIVE, objectId = mCallInfo.id,
            goneBottom = true,
            onMessageClickListener = { info ->
                if (isCreated()) {
                    showChatMessage(info.toUserBasicVo())
                }
            },
            onFollowerClickListener = {
                mBinding.vMessage.mBinding.baseMessage.clearFollower()
                mBinding.vHeader.updateFollowStatus(true)
            },
            onSelectMoreCardListener = {
                showSelectCard(it)
            },
            onGiftClickListener = {
                showGiftDialog(it.avatar, it.decoration?.avatarFrame)
            }
        )
    }

    //展示更多卡片
    private fun showSelectCard(infoOtherResp: InfoOtherResp) {
        GlobalPopupManager.showLiveSelectMoreCard(
            requireContext(), this, mViewModel,
            infoOtherResp, mCallInfo.id, mCallInfo.userId,
            onAtClickListener = {
                mBinding.vEdit.atUser(infoOtherResp.userId, infoOtherResp.nickname)
            }
        )
    }

    //通话是否已经结束
    private fun isEnded(): Boolean {
        return mCallInfo.status == LiveConst.CallState.OVER
    }

    //是接收方
    private fun isAnswer(): Boolean {
        return mCallInfo.answerId == UserManager.getUserId()
    }

    //是付费方
    private fun isPayer(): Boolean {
        return mCallInfo.payUserId == UserManager.getUserId()
    }

    //拨打中
    private fun isStarted(): Boolean {
        return mCallInfo.status == LiveConst.CallState.START
    }

    //通话是否准备好了
    private fun isConnected(): Boolean {
        return mCallInfo.status == LiveConst.CallState.CONNECTED
    }

    /**
     * 展示消息列表
     */
    private fun showChatMessage(userBase: UserBasicVo) {
        childFragmentManager.showNewDialogFragment(
            MessageSingleDialogFragment(
                userBase.userId,
                userBase.avatar,
                userBase.avatarFrame,
                userBase.chatBubble,
                nestedPage = false,
                singlePage = true,
                false
            ), MessageSessionFragment.FRAGMENT_TAG
        )
    }

    private var _otherMessageUser: UserBasicVo? = null

    //获取对方的基本信息
    private fun getOtherUser(): UserBasicVo? {
        return _otherMessageUser ?: let {
            LiveUtils.getCallOtherUser(mCallBean, mCallMessage, mOtherUserBasic).apply {
                mOtherUserBasic = this
            }
        }
    }

    private fun getOtherUserId() = if (mCallInfo.senderId != UserManager.getUserId()) {
        mCallInfo.senderId
    } else {
        mCallInfo.answerId
    }

    private fun showStopPopup() {
        XPopupUtils.showViewPopup(
            CallHangUpDialog(
                requireContext(),
                mCallInfo.getTime ?: CacheUtil.getServerTime(),
                isPayer(),
                isFree,
                true
            ) {
                val type = if (isStarted()) {
                    LiveConst.CloseType.CANCEL
                } else {
                    LiveConst.CloseType.END
                }
                mViewModel.callEnd(mCallInfo.id, type, UserManager.getUserId(), true)
            },
            lifecycle = lifecycle
        )
    }

    /**
     * ====================callback======================
     */

    fun setOnTranslateChangeListener(l: OnTranslationChangeListener) {
        mOnTranslateChange = l
    }

    override fun onShowView() {
    }

    override fun onHideView() {
    }

    override fun onBackPressed(): Boolean {
        if (!isCreated() || activity?.isFinishing != false) {
            return true
        }

        showStopPopup()

        return true
    }

    override fun setOnLiveCallCallback(l: OnLiveCallCallback) {
        mOnLiveCallCallback = l
    }

    override fun onAnswerSuccess(callBean: CallStartResp, callMessage: CallSignalingMessage) {
        withLoaded {
            mCallBean = callBean
            onAnswerSuccess(callMessage)
        }
    }

    private fun onAnswerSuccess(callMessage: CallSignalingMessage) {
        mCallMessage = callMessage
        if (!isConnected() && mPlayFirstFrame) {
            connected()
        }
    }

    override fun onPlayFirstFrame() {
        withLoaded {
            if (!isConnected()) {
                connected()
            }
            mPlayFirstFrame = true
        }
    }

    override fun onTranslating(model: RecognizeModel) {
        mBinding.vTransition.onTranslationText(getOtherUser(), model)
    }

    override fun onTranslated(model: RecognizeModel) {
        mBinding.vTransition.onTranslationText(getOtherUser(), model)
    }

    override fun onChangeCamera() {
        mOnGameCallListener?.onGameChangeCamera()
    }

    /**
     * =========================setListener===================
     */
    fun setOnGameCallListener(l: OnGameCallListener) {
        mOnGameCallListener = l
    }

    /**
     * ===================game=========================================
     */

    /**
     * 操作声音
     */
    private fun muteSound() {
        mBinding.btnVoice.setImageResource(if (mMuteSoundVoice) drawable.game_call_voic_close else drawable.game_call_voic_open)
        val mute = if (mLocalGameStatus == GamePlayFragment.GAME_START_PLAY) {
            mMuteSoundVoice
        } else {
            true
        }
        val engine = LiveEngineManage.getGameEngineHandler()?.getEngine()
        engine?.apply {
            muteGameSoundEffect(mute)
            muteGameMusic(true)
        }
    }

    /**
     * 重新加载游戏
     */
    fun reloadGame() {
        if (isDestroyView()) {
            return
        }
        mReloadGame = true
        mGameLoad = false
        LiveEngineManage.getGameEngineHandler()?.unloadGame(true)

        LogExt.logI(TAG, "reloadGame: gamecall")
    }

    /**
     * 加载游戏
     */
    private fun loadGame() {
        if (mGameLoad) {
            return
        }
        withLoaded {
            mGameLoad = true
            val isInit = LiveEngineManage.getGameEngineHandler()?.getEngine()?.isInit
            if (isInit == true) {
                goToLoadGame()
            } else {
                LiveEngineManage.getGameEngineHandler()?.initEngIne { errorCode, _ ->
                    if (errorCode == 0 || errorCode == ZegoGameEngineError.ERROR_ALREADY_INIT) {
                        goToLoadGame()
                    } else {
                        mGameLoad = false
                    }
                }
            }
            LogExt.logI(
                TAG,
                "loadGame: gamecall, isInit = $isInit"
            )
        }
    }

    private fun goToLoadGame() {
        if (isDestroyView()) {
            return
        }
        muteSound()
        LiveEngineManage.getGameEngineHandler()?.preloadGame(mGameMiniId, preGameListener)
        LogExt.logI(
            TAG,
            "goToLoadGame: gamecall, gameId = $mGameMiniId"
        )
    }

    private val preGameListener = object : PreGameListener {
        override fun callback(errorCode: Int, progress: Int) {
            LogExt.logI("--ZegoGame", "preloadGame------$errorCode   $progress-----")
            if (isCreated() && ((errorCode == 0 && progress == 100) || errorCode != 0)) { //预加载失败也直接加载
                LiveEngineManage.getGameEngineHandler()
                    ?.loadGame(mRoomId, mGameMiniId, mBinding.gameFl) { errorCode ->
                        if (errorCode != ZegoGameEngineError.SUCCESS) {
                            reloadGame()
                        }
                    }
                mStartLoadGameTime = System.currentTimeMillis()
            } else {
                mGameLoad = false
            }
        }

    }

    /**
     * 开始游戏 服务器返回可开始
     */
    private fun startGame() {
        if (isCreated()) {
            LiveEngineManage.getGameEngineHandler()?.startGame(
                mGameMiniId,
                mutableListOf(
                    UserManager.getUserId().toString(),
                    getOtherUserId().toString()
                )
            ) {
                if (it != 0) {
                    ToastGravity.showGravity(R.string.game_start_error)
                }
            }
        }
    }

    /**
     * 服务器游戏状态更新
     */
    private fun updateGameStatus(gameStatus: Int) {
        if (isDestroyView()) {
            return
        }
        //资源没加载完
        if (mLocalGameStatus < GamePlayFragment.GAME_LOADED) {
            mBinding.playTipsTv.text = StringUtils.getString(R.string.game_resources_loading)
            return
        }

        when (gameStatus) {
            0 -> {
                mBinding.playTipsTv.text = StringUtils.getString(R.string.game_wait)
            }

            1 -> {
                mBinding.playTipsTv.text = StringUtils.getString(R.string.begin_in_minute)
            }

            2 -> {

            }

            3 -> {
                mBinding
                mBinding.playTipsTv.text = StringUtils.getString(R.string.in_settlement)
            }
        }

    }

    private val mZegoGameEngineHandler = object : ZegoGameEngineHandler() {
        override fun onGameLoadStateUpdate(gameLoadState: ZegoGameLoadState?) {
            // 通知游戏加载的状态
            when (gameLoadState) {
                ZegoGameLoadState.ZegoGameLoading -> {
                    mLocalGameStatus = GAME_LOAD

                    reportEvent(ZegoGameEvent.GAME_LOAD_STATE_UPDATE, "0")
                }

                ZegoGameLoadState.ZegoGameLoaded -> {
                    muteSound()
                    mLocalGameStatus = GAME_LOADED

                    updateGameStatus(mGameStatus)

                    //上报加载时间
                    val duration = System.currentTimeMillis() - mStartLoadGameTime //加载时间
                    TrackHelper.postTrack(
                        this@GameCallVideoFragment,
                        TrackEventConst.GAME_LOAD_TIME,
                        params = TrackHelper.rechargeForMap(mutableMapOf("time" to duration.toString()))
                    )
                    Firebase.analytics.postEvent(
                        EventConst.ZEGO_GAME_LOAD_DURATION,
                        bundleOf(
                            "time" to duration.toString()
                        )
                    )
                    reportEvent(ZegoGameEvent.GAME_LOAD_STATE_UPDATE, "1")
                }

                null -> {}
            }
        }

        override fun onGameStateUpdate(gameState: ZegoGameState?, reasonCode: Int) {
            when (gameState) {
                ZegoGameState.ZegoGamePlaying -> {
                    mLocalGameStatus = GAME_START_PLAY
                    muteSound()
                }

                ZegoGameState.ZegoGameOver -> {
                    mLocalGameStatus = GAME_STOP_PLAY
                    mBinding.gameFl.visibility = View.GONE
                }

                ZegoGameState.ZegoGameIdle -> {
                    mLocalGameStatus = GAME_READY
                }

                else -> {}
            }
            val params = buildMap {
                put("reasonCode", reasonCode.toString())
                gameState?.let {
                    put("gameState", gameState.ordinal.toString())
                }
            }
            reportEvent(ZegoGameEvent.GAME_STATE_UPDATE, params)
        }

        override fun onPlayerStateUpdate(playerState: ZegoGamePlayerState?) {
            when (playerState) {
                ZegoGamePlayerState.ZegoGamePlayerStartPlay -> { //游戏开始
                    narrow()
                    mBinding.apply {
                        vTransition.foldAndUnfold(false)
                        gameFl.visibility = View.VISIBLE
                        vsImg.visibility = View.VISIBLE
                        joinBtn.visibility = View.VISIBLE
                        exitGame.visibility = View.GONE
                        //游戏开始隐藏周星
                        weekStar.visibility = View.GONE
                        mViewModel.cancelPollingWeeklyStarRank()
                    }
                    reportEvent(ZegoGameEvent.PLAYER_STATE_UPDATE, "0")
                }

                ZegoGamePlayerState.ZegoGamePlayerStopPlay -> {//游戏结束
                    enlarge()
                    mBinding.apply {
                        gameFl.visibility = View.GONE
                        vsImg.visibility = View.GONE
                    }

                    mViewModel.getWeeklyStarRank()
                    reportEvent(ZegoGameEvent.PLAYER_STATE_UPDATE, "1")
                }

                null -> {}
            }

        }

        override fun onUnloaded(gameID: String?) {
            mLocalGameStatus = GAME_UNLOAD

            if (mReloadGame) {
                mReloadGame = false
                if (LiveEngineManage.getGameEngineHandler()?.getEngine()?.isInit == true) {
                    goToLoadGame()
                } else {
                    LiveEngineManage.getGameEngineHandler()?.initEngIne { errorCode, _ ->
                        if (errorCode == 0 || errorCode == ZegoGameEngineError.ERROR_ALREADY_INIT) {
                            goToLoadGame()
                        }
                    }
                }
            }

            LogExt.logI(TAG, "onUnloaded: callId = ${mCallInfo?.id}, gameId = $gameID")
        }

        override fun onGameError(errorCode: Int, errorMessage: String?) {
            val params = buildMap {
                put("errorCode", errorCode.toString())
                errorMessage?.let {
                    put("errorMessage", it)
                }
            }
            reportEvent(ZegoGameEvent.GAME_ERROR, params)
        }

        override fun onGameResult(result: String?) {
            result?.let {
                reportEvent(ZegoGameEvent.GAME_RESULT, it)
            }
        }
    }

    private fun reportEvent(event: Int, params: Any) {
        val info = mCallInfo

        val finalParams = if (params is String) {
            params
        } else {
            JsonUtils.toJson(params)
        }

        mViewModel.zegoGameEvent(
            ZegoGameEventBean(
                info.id,
                LiveConst.GameBusinessType.CALL,
                event,
                finalParams
            )
        )
    }

    /**
     * ---------------------game--------end---------------------------
     */
    override fun onDestroy() {
        super.onDestroy()
        EventBus.getDefault().unregister(this)
        AppUtils.unregisterAppStatusChangedListener(mOnAppStatusChangedListener)
        isInitTranslation = false
        mOnTranslateChange?.onTranslationSwitch(isOpen = false, needUnInit = true)
        LiveEngineManage.eventHandlerHelper.removeEventHandler(mEventHandler)
        LiveEngineManage.getGameEngineHandler()?.unloadGame()
        LiveEngineManage.getGameEngineHandler()?.removePreGameListener(preGameListener)
    }

    /**
     * 缩小
     */
    private fun narrow() {
        var lp = mBinding.cvCl.layoutParams as MarginLayoutParams
        lp.height = 120.autoDp
        mBinding.cvCl.layoutParams = lp
    }

    /**
     * 放大
     */
    private fun enlarge() {
        var lp = mBinding.cvCl.layoutParams as MarginLayoutParams
        lp.height = 217.autoDp
        mBinding.cvCl.layoutParams = lp
    }

    /**
     * 缩小
     */
    private val narrowAnimator by lazy {
        var lp = mBinding.cvCl.layoutParams as MarginLayoutParams
        ValueAnimator.ofInt(217.autoDp, 120.autoDp).apply {
            duration = 500
            addUpdateListener {
                lp.height = it.animatedValue as Int
                mBinding.cvCl.layoutParams = lp
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    mBinding.vsImg.visibility = View.VISIBLE
                }
            })
        }
    }

    /**
     * 放大
     */
    private val enlargeAnimator by lazy {
        var lp = mBinding.cvCl.layoutParams as MarginLayoutParams
        ValueAnimator.ofInt(120.autoDp, 217.autoDp).apply {
            duration = 500
            addUpdateListener {
                lp.height = it.animatedValue as Int
                mBinding.cvCl.layoutParams = lp
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    mBinding.vsImg.visibility = View.GONE
                }
            })
        }
    }

    /**
     * 在后台计时到
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onBackGroundEvent(event: BackgroundEvent) {
        if (isAnswer()) {
            mViewModel.callEnd(
                mCallInfo.id,
                LiveConst.CloseType.ERROR,
                UserManager.getUserId()
            )
        }
    }

    companion object {

        const val TAG = "GameCallVideoFragment"

        private const val pageType = LiveConst.Page.CALL

        private const val maxBackgroundTime = 20000L //接听方在后台停留挂断事件

        const val GAME_UNLOAD = 1000000 //游戏未加载
        const val GAME_LOAD = 1000001 //游戏加载中
        const val GAME_LOADED = 1000002 //游戏加载完成
        const val GAME_START_PLAY = 1000003 //游戏开始
        const val GAME_STOP_PLAY = 1000004 //游戏结束
        const val GAME_READY = 1000005 //游戏空闲
        const val GAME_TIME = 5000L //等待結算时间
    }

}
